/**
 * Copyright (c) 2010 CEPRI,Inc.All rights reserved.
 * Created by 2010-9-3 
 */
package cn.jdy.payment.service.classify;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.stereotype.Service;

import cn.jdy.common.constant.BankConstant;
import cn.jdy.framework.log.BaseLog;
import cn.jdy.payment.entity.MerchantInfo;
import cn.jdy.payment.entity.Orders;
import cn.jdy.payment.service.BankBusiServer;

/**
 * 支付宝个性业务处理类
 *
 * @author Zhang Yuyong
 */
@Service("bankBusi" + BankConstant.BANKNO_ALIPAY)
public class AlipayService extends BankBusiServer {

	/**
	 * 生成支付宝订单
	 */
	public final Orders placeOrder(Orders order, MerchantInfo merchant) throws UnsupportedEncodingException {
		Map<String, String> paraMap = new TreeMap<String, String>();
		paraMap.put("service", merchant.getPayChannel().getInterface_pay());
		paraMap.put("partner", merchant.getMerId());
		paraMap.put("payment_type", "1");
		paraMap.put("notify_url", merchant.getPayChannel().getGateWay());
		paraMap.put("out_trade_no", order.getId());
		paraMap.put("return_url", merchant.getPayChannel().getNotifyAddrToPage());
		paraMap.put("_input_charset", BankConstant.ALIPAY_CHARSET);
		paraMap.put("total_fee", order.getAmount());
		paraMap.put("seller_email", merchant.getMerAcct());
		paraMap.put("subject", order.getGoodsName());
		paraMap.put("sign", DigestUtils.md5Hex(createLinkString(paraMap, '&').concat(merchant.getPrivateKey()).getBytes(BankConstant.ALIPAY_CHARSET)));
		paraMap.put("sign_type", BankConstant.ALIPAY_SIGNTYPE);
		order.setParaMap(paraMap);
		return order;
	}

	/**
	 * 银行回调
	 */
	@Override
	public Orders notify(Map<String, String> param) {

		Orders order;

		String orderNo = param.get("out_trade_no");
		String notifyDate = param.get("notify_time");
		String status = param.get("is_success");
		String amount = param.get("total_fee");
		String outNo = param.get("trade_no");
		try {
			MerchantInfo merchant = merchantService.queryMerchantById(BankConstant.BANKNO_ALIPAY);
			if(!verify(param, merchant)) return null;

			order = orderService.find(orderNo);
			if(!verify(notifyDate, String.format("%.2f", Double.valueOf(amount)), order)) return null;

			if(BankConstant.ORDER_SUC.equals(order.getStatus())) return order;

			order.setStatus(BankConstant.ALIPAY_RESULT_SUC.equals(status) ? BankConstant.ORDER_SUC : BankConstant.ORDER_FAIL);
			order.setNotifyDate(notifyDate);
			order.setOutNo(outNo);
		} catch(Exception e) {
			order = null;
			BaseLog.e(this.getClass(), "notify 银行回调方法异常", e);
		}
		return order;
	}

	/**
	 * 把数组所有元素排序，并按照“参数=参数值”的模式用“&”字符拼接成字符串
	 *
	 * @param params 需要排序并参与字符拼接的参数组
	 * @return 拼接后字符串
	 */
	public String createLinkString(Map<String, String> params, char connector) {
		List<String> keys = new ArrayList<String>(params.keySet());
		Collections.sort(keys);
		StringBuilder sbd = new StringBuilder();

		for(String key : keys) {
			String value = params.get(key);
			if(value == null || value.length() == 0 || key.equalsIgnoreCase("sign") || key.equalsIgnoreCase("sign_type"))
				continue;
			else sbd.append(connector).append(key).append("=").append(params.get(key));
		}
		return sbd.substring(1);
	}

	/**
	 * 支付宝解密
	 */
	public boolean verify(Map<String, String> param, MerchantInfo merchant) throws UnsupportedEncodingException {
		return param.get("sign").equals(DigestUtils.md5Hex(createLinkString(param, '&').concat(merchant.getPrivateKey()).getBytes(BankConstant.ALIPAY_CHARSET)));
	}

}
